import json
import tkinter as tk
from tkinter import ttk, messagebox
import qrcode
from PIL import Image, ImageTk
import sys
import os
from ctypes import windll
# Windows系统专用
try:
    windll.shcore.SetProcessDpiAwareness(1)  # 启用DPI感知
except:
    pass  # 非Windows系统忽略

def get_resource_path(relative_path):
    """获取资源的绝对路径"""
    try:
        if getattr(sys, 'frozen', False):
            # 打包环境
            base_path = sys._MEIPASS
        else:
            # 开发环境：直接使用当前文件所在目录的父目录（项目根目录）
            current_file_path = os.path.abspath(__file__)
            # 当前文件在项目根目录下，所以直接使用当前目录
            base_path = os.path.dirname(current_file_path)
        
        # 构建完整路径
        resource_path = os.path.join(base_path, 'raw', relative_path)
        
        # 调试信息
        print(f"🔍 资源路径信息:")
        print(f"   运行环境: {'打包' if getattr(sys, 'frozen', False) else '开发'}")
        print(f"   当前文件: {os.path.abspath(__file__)}")
        print(f"   基础路径: {base_path}")
        print(f"   资源路径: {resource_path}")
        print(f"   文件存在: {os.path.exists(resource_path)}")
        
        return resource_path
        
    except Exception as e:
        print(f"❌ 获取资源路径失败: {e}")
        # 回退方案
        return os.path.join('raw', relative_path)


class LibrarySeatSelector:
    def __init__(self, root):
        self.root = root
        self.root.title("图书馆座位二维码生成器")
        self.root.geometry("1000x850")
        self.root.configure(bg='lightblue')
        
        self.load_data()  # 加载座位数据
        self.create_widgets()  # 创建界面组件
    
    def load_data(self):
        """加载JSON格式的座位数据"""
        try:
            file_path = get_resource_path("library_seats_reorganized.json")
            with open(file_path, 'r', encoding='utf-8') as file:
                self.data = json.load(file)
        except Exception as e:
            messagebox.showerror("错误", f"无法加载座位数据: {str(e)}")
            self.data = []
            self.root.destroy()
    
    def create_widgets(self):
        """创建主界面布局"""
        # 左右分栏布局
        main_paned = ttk.PanedWindow(self.root, orient=tk.HORIZONTAL)
        main_paned.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 左侧选择区域
        left_frame = ttk.Frame(main_paned, padding="10",width=450)
        left_frame.pack_propagate(False)  # 禁止自动调整大小
        main_paned.add(left_frame, weight=1)
        
        # 右侧二维码区域
        right_frame = ttk.Frame(main_paned, padding="10")
        main_paned.add(right_frame, weight=4)
        
        self.create_left_widgets(left_frame)  # 左侧组件
        self.create_right_widgets(right_frame)  # 右侧组件
    
    def create_left_widgets(self, parent):
        """创建左侧选择组件"""
        # 标题
        ttk.Label(parent, text="图书馆座位选择系统", font=("Arial", 16, "bold")).pack(pady=(0, 20))
        
        # 直接输入区域
        direct_frame = ttk.LabelFrame(parent, text="直接输入座位名称", padding="10")
        direct_frame.pack(fill=tk.X, pady=(0, 10))
        
        input_row = ttk.Frame(direct_frame)
        input_row.pack(fill=tk.X, pady=(0, 10))

        ttk.Label(input_row, text="座位名称:").pack(side=tk.LEFT, padx=(0, 10))
        self.direct_input_var = tk.StringVar()
        self.direct_input_entry = ttk.Entry(input_row, textvariable=self.direct_input_var, width=25)
        self.direct_input_entry.pack(side=tk.LEFT, padx=(0, 10))
        self.direct_input_entry.bind('<Return>', lambda event: self.generate_from_direct_input())

        # 按钮单独一行，居中放置
        button_row = ttk.Frame(direct_frame)
        button_row.pack(fill=tk.X)
        ttk.Button(button_row, text="生成二维码", command=self.generate_from_direct_input).pack(pady=5)
        
        # 楼层选择
        floor_frame = ttk.LabelFrame(parent, text="选择楼层", padding="10")
        floor_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Label(floor_frame, text="楼层:").grid(row=0, column=0, padx=(0, 10))
        self.floor_var = tk.StringVar()
        self.floor_combo = ttk.Combobox(floor_frame, textvariable=self.floor_var, state="readonly", width=30)
        self.floor_combo.grid(row=0, column=1, sticky=tk.EW)
        self.floor_combo.bind("<<ComboboxSelected>>", self.on_floor_selected)
        
        # 自习室选择
        self.room_frame = ttk.LabelFrame(parent, text="选择自习室", padding="10")
        self.room_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Label(self.room_frame, text="自习室:").grid(row=0, column=0, padx=(0, 10))
        self.room_var = tk.StringVar()
        self.room_combo = ttk.Combobox(self.room_frame, textvariable=self.room_var, state="readonly", width=30)
        self.room_combo.grid(row=0, column=1, sticky=tk.EW)
        self.room_combo.bind("<<ComboboxSelected>>", self.on_room_selected)
        
        # 座位选择区域 - 修改为固定高度并显示滚动条
        self.device_frame = ttk.LabelFrame(parent, text="选择座位", padding="10")
        self.device_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))  # 修改为可扩展
        
        # 创建主容器框架
        device_container = ttk.Frame(self.device_frame)
        device_container.pack(fill=tk.BOTH, expand=True)
        
        # 创建Canvas和Scrollbar
        self.device_canvas = tk.Canvas(device_container, height=300)  # 固定高度
        self.device_scrollbar = ttk.Scrollbar(device_container, orient="vertical", command=self.device_canvas.yview)
        
        # 可滚动框架
        self.scrollable_device_frame = ttk.Frame(self.device_canvas)
        self.scrollable_device_frame.bind(
            "<Configure>",
            lambda e: self.device_canvas.configure(scrollregion=self.device_canvas.bbox("all"))
        )
        
        # 将可滚动框架添加到Canvas
        self.canvas_window = self.device_canvas.create_window((0, 0), window=self.scrollable_device_frame, anchor="nw")
        
        # 配置Canvas滚动
        self.device_canvas.configure(yscrollcommand=self.device_scrollbar.set)
        
        # 绑定滚轮事件
        self.device_canvas.bind("<MouseWheel>", self.on_mousewheel)
        self.scrollable_device_frame.bind("<MouseWheel>", self.on_mousewheel)
        
        # 布局Canvas和Scrollbar - 使用grid确保正确显示
        self.device_canvas.grid(row=0, column=0, sticky="nsew")
        self.device_scrollbar.grid(row=0, column=1, sticky="ns")
        
        # 配置容器网格权重
        device_container.columnconfigure(0, weight=1)
        device_container.rowconfigure(0, weight=1)
        
        # 初始提示
        ttk.Label(self.scrollable_device_frame, text="请先选择楼层和自习室").pack(pady=50)
        
        # 选择按钮
        self.select_button = ttk.Button(parent, text="确认选择", command=self.show_selection_result)
        self.select_button.pack(pady=10)
        self.select_button.pack_forget()  # 初始隐藏
        
        # 绑定Canvas大小变化事件，调整内部框架宽度
        def configure_canvas(event):
            # 调整内部框架宽度与Canvas一致
            self.device_canvas.itemconfig(self.canvas_window, width=event.width)
        
        self.device_canvas.bind("<Configure>", configure_canvas)
        
        self.populate_floors()  # 填充楼层数据

    
    def create_right_widgets(self, parent):
        """创建右侧二维码显示组件"""
        ttk.Label(parent, text="座位二维码", font=("Arial", 14, "bold")).pack(pady=(0, 20))
        
        self.qr_frame = ttk.LabelFrame(parent, text="二维码预览", padding="10")
        self.qr_frame.pack(fill=tk.BOTH, expand=True)
        
        # 初始提示标签
        self.qr_label = ttk.Label(self.qr_frame, text="请先选择座位以生成二维码", font=("Arial", 12), justify=tk.CENTER)
        self.qr_label.pack(expand=True)
        
        self.current_labId = None  # 当前实验室ID
        self.current_devId = None  # 当前设备ID
    


    
    def on_mousewheel(self, event):
        """处理鼠标滚轮滚动事件"""
        self.device_canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
    
    def populate_floors(self):
        """填充楼层选择下拉框"""
        floors = [item["room_floor"] for item in self.data]
        self.floor_combo["values"] = floors
        if floors:
            self.floor_combo.current(0)
            self.on_floor_selected(None)
    
    def on_floor_selected(self, event):
        """楼层选择事件处理"""
        selected_floor = self.floor_var.get()
        if not selected_floor: return
        
        # 查找对应楼层数据
        floor_data = next((item for item in self.data if item["room_floor"] == selected_floor), None)
        if floor_data:
            # 填充自习室下拉框
            rooms = [room["room_name"] for room in floor_data["area_room"]]
            self.room_combo["values"] = rooms
            if rooms:
                self.room_combo.current(0)
                self.on_room_selected(None)
            else:
                self.clear_device_selection()
    

    def clear_qr_code(self):
        """清空二维码显示区域"""
        for widget in self.qr_frame.winfo_children():
            widget.destroy()
        self.qr_label = ttk.Label(self.qr_frame, text="请先选择座位以生成二维码", font=("Arial", 12), justify=tk.CENTER)
        self.qr_label.pack(expand=True)
    
    def on_room_selected(self, event):
        """自习室选择事件处理"""
        selected_floor, selected_room = self.floor_var.get(), self.room_var.get()
        if not selected_floor or not selected_room:
            self.clear_device_selection()
            return
        
        # 查找对应自习室数据
        floor_data = next((item for item in self.data if item["room_floor"] == selected_floor), None)
        if not floor_data: return
        
        room_data = next((room for room in floor_data["area_room"] if room["room_name"] == selected_room), None)
        if not room_data or "devices" not in room_data:
            self.clear_device_selection()
            return
        
        self.current_labId = room_data.get("labId")  # 保存实验室ID
        
        # 清空并重新创建设备选择区域
        for widget in self.scrollable_device_frame.winfo_children():
            widget.destroy()
        
        devices = room_data["devices"]
        if not devices:
            ttk.Label(self.scrollable_device_frame, text="该自习室暂无可用座位").pack(pady=50)
            self.clear_qr_code()
        else:
            # 创建设备单选按钮 - 每行三列布局
            self.device_var = tk.StringVar()
            
            # 创建框架容器用于网格布局
            grid_frame = ttk.Frame(self.scrollable_device_frame)
            grid_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
            
            # 计算行数和列数
            num_devices = len(devices)
            num_columns = 3
            num_rows = (num_devices + num_columns - 1) // num_columns  # 向上取整
            
            # 创建设备选择按钮网格
            for i, device in enumerate(devices):
                row = i // num_columns
                col = i % num_columns
                
                # 创建单选按钮，添加一些内边距使布局更美观
                rb = ttk.Radiobutton(
                    grid_frame, 
                    text=device["devName"], 
                    value=device["devName"], 
                    variable=self.device_var
                )
                rb.grid(
                    row=row, 
                    column=col, 
                    padx=10, 
                    pady=5, 
                    sticky="w"
                )
            
            # 配置网格权重，使列均匀分布
            for col in range(num_columns):
                grid_frame.columnconfigure(col, weight=1)
            
            self.select_button.pack(side=tk.BOTTOM, fill=tk.X, pady=10)  # 显示选择按钮

    def clear_device_selection(self):
        """清空座位选择区域"""
        for widget in self.scrollable_device_frame.winfo_children():
            widget.destroy()
        
        # 创建提示标签的容器，使其居中显示
        prompt_frame = ttk.Frame(self.scrollable_device_frame)
        prompt_frame.pack(expand=True, fill=tk.BOTH)
        
        ttk.Label(prompt_frame, text="请先选择楼层和自习室", font=("Arial", 10)).place(relx=0.5, rely=0.5, anchor="center")
        
        self.select_button.pack_forget()  # 隐藏选择按钮
        self.clear_qr_code()  # 清空二维码

    def generate_qr_code(self, labId, devId):
        """生成二维码图像"""
        data = f"http://update.unifound.net/wxnotice/s.aspx?c={labId}_Seat_{devId}_1JX"  # 二维码数据
        img = qrcode.make(data).resize((300, 300), Image.Resampling.LANCZOS)  # 生成并调整大小
        return ImageTk.PhotoImage(img), data  # 返回图像对象和数据
    
    def show_selection_result(self):
        """显示选择结果和生成二维码"""
        selected_device = self.device_var.get()
        if not selected_device:
            messagebox.showwarning("警告", "请先选择一个座位")
            return
        
        # 查找设备ID - 同时确保获取labId
        selected_floor, selected_room = self.floor_var.get(), self.room_var.get()
        floor_data = next((item for item in self.data if item["room_floor"] == selected_floor), None)
        if not floor_data: return
        
        room_data = next((room for room in floor_data["area_room"] if room["room_name"] == selected_room), None)
        if not room_data: return
        
        # 关键修复：确保current_labId被正确设置
        self.current_labId = room_data.get("labId")
        
        device_data = next((dev for dev in room_data["devices"] if dev["devName"] == selected_device), None)
        if not device_data: return
        
        self.current_devId = device_data["devId"]  # 保存设备ID
        
        if self.current_labId and self.current_devId:
            qr_image, qr_data = self.generate_qr_code(self.current_labId, self.current_devId)
            if qr_image:
                for widget in self.qr_frame.winfo_children():
                    widget.destroy()
                
                # 创建容器框架来组织二维码和相关信息
                container = ttk.Frame(self.qr_frame)
                container.pack(expand=True, pady=20)
                
                # 显示二维码
                qr_label = ttk.Label(container, image=qr_image)
                qr_label.image = qr_image  # 保持引用
                qr_label.pack(pady=(0, 15))
                
                # 信息显示区域
                info_frame = ttk.Frame(container)
                info_frame.pack(fill=tk.X, padx=20)
                
                # 座位名称（可复制）
                ttk.Label(info_frame, text="座位:", font=("Arial", 12)).grid(row=0, column=0, sticky="w", pady=5)
                seat_entry = ttk.Entry(info_frame, font=("Arial", 12), width=25, state="readonly")
                seat_entry.grid(row=0, column=1, sticky="ew", pady=5, padx=(10, 0))
                seat_entry.configure(state="normal")
                seat_entry.insert(0, selected_device)
                seat_entry.configure(state="readonly")
                
                # 设备ID（可复制）
                ttk.Label(info_frame, text="设备ID:", font=("Arial", 12)).grid(row=1, column=0, sticky="w", pady=5)
                devid_entry = ttk.Entry(info_frame, font=("Arial", 12), width=25, state="readonly")
                devid_entry.grid(row=1, column=1, sticky="ew", pady=5, padx=(10, 0))
                devid_entry.configure(state="normal")
                devid_entry.insert(0, self.current_devId)
                devid_entry.configure(state="readonly")
                
                # URL链接（可复制）+ 复制按钮
                ttk.Label(info_frame, text="URL链接:", font=("Arial", 12)).grid(row=2, column=0, sticky="w", pady=5)
                
                # URL输入框和按钮的容器
                url_frame = ttk.Frame(info_frame)
                url_frame.grid(row=2, column=1, sticky="ew", pady=5, padx=(10, 0))
                
                url_entry = ttk.Entry(url_frame, font=("Arial", 10), state="readonly")
                url_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
                url_entry.configure(state="normal")
                url_entry.insert(0, qr_data)
                url_entry.configure(state="readonly")
                
                # 一键复制按钮
                copy_button = ttk.Button(url_frame, text="复制", width=6, 
                                    command=lambda: self.copy_to_clipboard(qr_data))
                copy_button.pack(side=tk.RIGHT, padx=(5, 0))
                
                # 设置列权重，使输入框可以扩展
                info_frame.columnconfigure(1, weight=1)
                url_frame.columnconfigure(0, weight=1)

    def generate_from_direct_input(self):
        """根据直接输入的座位名称生成二维码"""
        dev_name = self.direct_input_var.get().strip()
        if not dev_name:
            messagebox.showwarning("警告", "请输入座位名称")
            return
        
        # 在所有数据中搜索匹配的座位
        for floor in self.data:
            for room in floor["area_room"]:
                if "devices" in room:
                    for device in room["devices"]:
                        if device["devName"].upper() == dev_name.upper():
                            # 找到匹配座位，更新界面
                            self.current_labId, self.current_devId = room.get("labId"), device["devId"]
                            self.floor_var.set(floor["room_floor"])
                            self.room_var.set(room["room_name"])
                            self.on_room_selected(None)
                            self.device_var.set(dev_name)
                            
                            # 生成二维码
                            qr_image, qr_data = self.generate_qr_code(self.current_labId, self.current_devId)
                            if qr_image:
                                for widget in self.qr_frame.winfo_children():
                                    widget.destroy()
                                
                                # 创建容器框架来组织二维码和相关信息
                                container = ttk.Frame(self.qr_frame)
                                container.pack(expand=True, pady=20)
                                
                                # 显示二维码
                                qr_label = ttk.Label(container, image=qr_image)
                                qr_label.image = qr_image
                                qr_label.pack(pady=(0, 15))
                                
                                # 信息显示区域
                                info_frame = ttk.Frame(container)
                                info_frame.pack(fill=tk.X, padx=20)
                                
                                # 座位名称（可复制）
                                ttk.Label(info_frame, text="座位:", font=("Arial", 12)).grid(row=0, column=0, sticky="w", pady=5)
                                seat_entry = ttk.Entry(info_frame, font=("Arial", 12), width=25, state="readonly")
                                seat_entry.grid(row=0, column=1, sticky="ew", pady=5, padx=(10, 0))
                                seat_entry.configure(state="normal")
                                seat_entry.insert(0, dev_name)
                                seat_entry.configure(state="readonly")
                                
                                # 设备ID（可复制）
                                ttk.Label(info_frame, text="设备ID:", font=("Arial", 12)).grid(row=1, column=0, sticky="w", pady=5)
                                devid_entry = ttk.Entry(info_frame, font=("Arial", 12), width=25, state="readonly")
                                devid_entry.grid(row=1, column=1, sticky="ew", pady=5, padx=(10, 0))
                                devid_entry.configure(state="normal")
                                devid_entry.insert(0, self.current_devId)
                                devid_entry.configure(state="readonly")
                                
                                # URL链接（可复制）+ 复制按钮
                                ttk.Label(info_frame, text="URL链接:", font=("Arial", 12)).grid(row=2, column=0, sticky="w", pady=5)
                                
                                # URL输入框和按钮的容器
                                url_frame = ttk.Frame(info_frame)
                                url_frame.grid(row=2, column=1, sticky="ew", pady=5, padx=(10, 0))
                                
                                url_entry = ttk.Entry(url_frame, font=("Arial", 10), state="readonly")
                                url_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
                                url_entry.configure(state="normal")
                                url_entry.insert(0, qr_data)
                                url_entry.configure(state="readonly")
                                
                                # 一键复制按钮
                                copy_button = ttk.Button(url_frame, text="复制", width=6, 
                                                    command=lambda: self.copy_to_clipboard(qr_data))
                                copy_button.pack(side=tk.RIGHT, padx=(5, 0))
                                
                                # 设置列权重，使输入框可以扩展
                                info_frame.columnconfigure(1, weight=1)
                                url_frame.columnconfigure(0, weight=1)
                            return
        
        messagebox.showwarning("警告", f"未找到座位: {dev_name}")

    def copy_to_clipboard(self, text):
        """复制文本到剪贴板"""
        self.root.clipboard_clear()
        self.root.clipboard_append(text)
        self.root.update()  # 现在剪贴板内容会持续存在
        messagebox.showinfo("复制成功", "链接已复制到剪贴板！")
def main():
    """主函数"""
    root = tk.Tk()
    LibrarySeatSelector(root)
    root.mainloop()

if __name__ == "__main__":
    main()